package com.lemon.boot.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lemon.boot.common.entity.LoginUserDetail;
import com.lemon.boot.common.enums.RoleKeyEnum;
import com.lemon.boot.common.exception.CustomException;
import com.lemon.boot.common.service.ElasticsearchService;
import com.lemon.boot.common.utils.EasyExcelUtil;
import com.lemon.boot.common.utils.JwtUtil;
import com.lemon.boot.common.utils.LocalDateUtil;
import com.lemon.boot.common.utils.SecurityUtil;
import com.lemon.boot.dto.LogDTO;
import com.lemon.boot.po.LogPO;
import com.lemon.boot.service.IDeptUserService;
import com.lemon.boot.service.ILogService;
import com.lemon.boot.vo.LogExcelVO;
import lombok.extern.log4j.Log4j2;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchAllQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 李猛
 * @datetime 2024/3/3 11:22
 * @description 类对象
 */
@Log4j2
@Service
public class LogServiceImpl implements ILogService {
    @Resource
    private IDeptUserService iDeptUserService;
    @Resource
    private ElasticsearchService elasticsearchService;
    @Resource
    private HttpServletResponse httpServletResponse;

    @Override
    public String add(LogPO logPO) {
        return elasticsearchService.add(logPO) ? "添加成功！" : "添加失败！";
    }

    @Override
    public String del(Long id) {
        return elasticsearchService.del(id, LogPO.class) ? "删除成功！" : "删除失败！";
    }

    @Override
    public String edit(LogPO logPO) {
        return elasticsearchService.edit(logPO) ? "修改成功！" : "修改失败！";
    }

    @Override
    public LogPO get(Long id) {
        LogPO logPO = elasticsearchService.get(id, LogPO.class);
        logPO.setCreateTimeStr(LocalDateUtil.toString(logPO.getCreateTime()));
        return logPO;
    }

    @Override
    public Page<LogPO> page(LogDTO logDTO) {
        //1.当前用户
        final LoginUserDetail currentUser = JwtUtil.getCurrentUser();

        //2.初始化条件
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder().must(new MatchAllQueryBuilder());

        //3.判断用户角色
        if (!SecurityUtil.hasRole(currentUser, RoleKeyEnum.SUPER)) {
            if (SecurityUtil.hasRole(currentUser, RoleKeyEnum.ADMIN)) {
                boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("tenantId", currentUser.getTenantId()));
            } else {
                if (SecurityUtil.hasRole(currentUser, RoleKeyEnum.COMMON)) {
                    List<Long> userIdList = iDeptUserService.getChildUserIdByUserId(currentUser.getUserId());
                    boolQueryBuilder.must(QueryBuilders.termsQuery("userId", userIdList));
                } else {
                    throw new CustomException("用户角色信息异常");
                }
            }
        }

        //4.查询条件
        if (StringUtils.hasText(logDTO.getUserName())) {
            boolQueryBuilder.must(QueryBuilders.matchQuery("userName", logDTO.getUserName()));
        }
        if (logDTO.getStartDate() != null) {
            Long start = LocalDateUtil.toEpochMilli(logDTO.getStartDate());
            boolQueryBuilder.must(QueryBuilders.rangeQuery("createTime").gte(start));
        }
        if (logDTO.getEndDate() != null) {
            Long end = LocalDateUtil.toEpochMilli(logDTO.getEndDate());
            boolQueryBuilder.must(QueryBuilders.rangeQuery("createTime").lte(end));
        }

        //5.排序
        FieldSortBuilder sortBuilder = SortBuilders.fieldSort("createTime").order(org.elasticsearch.search.sort.SortOrder.DESC);

        Page<LogPO> page = elasticsearchService.page(boolQueryBuilder, sortBuilder, logDTO.getCurrent(), logDTO.getSize(), LogPO.class);
        page.getRecords().forEach(item -> item.setCreateTimeStr(LocalDateUtil.toString(item.getCreateTime())));
        return page;
    }

    @Override
    public void export(LogDTO logDTO) {
        //1.查询数据
        Page<LogPO> page = this.page(logDTO);

        //2.转换数据
        List<LogExcelVO> logExcelList = page.getRecords()
                .stream()
                .map(item -> LogExcelVO.builder()
                        .ip(item.getIp())
                        .uri(item.getUri())
                        .param(item.getParam())
                        .userName(item.getUserName())
                        .method(item.getMethod())
                        .createTimeStr(item.getCreateTimeStr())
                        .build())
                .collect(Collectors.toList());

        //3.文件名
        String fileName = String.format("操作日志-%s", LocalDateUtil.toString(LocalDate.now()));

        //4.sheet
        String sheet = LocalDateTime.now().format(LocalDateUtil.DATE_FORMATTER_3);

        //5.导出
        EasyExcelUtil.write(httpServletResponse, LogExcelVO.class, fileName, sheet, logExcelList);
    }
}
